﻿using gt.rediscache.core.Entry;
using gt.rediscache.core.Utility;
using StackExchange.Redis;
using System.Threading.Tasks;

namespace gt.rediscache.core.Clients
{
    public partial class RedisClient
    {
        public bool SortedSetAdd(string key, string member, double score, StackExchange.Redis.When when = When.Always, CommandFlags flags = CommandFlags.None)
        {
            var message = new SortedSetAddMessage(key, member, score, when);
            return Execute(RedisCommand.SortedSetAdd, message, flags).BoolResult;
        }

        public double SortedSetDecrement(string key, string member, double value, StackExchange.Redis.CommandFlags flags = CommandFlags.None)
        {
            var message = new SortedSetDecrementMessage(key, member, value);
            return Execute(RedisCommand.SortedSetDecrement, message, flags).DoubleResult;
        }

        public double SortedSetIncrement(string key, string member, double value, StackExchange.Redis.CommandFlags flags = CommandFlags.None)
        {
            var message = new SortedSetIncrementMessage(key, member, value);
            return Execute(RedisCommand.SortedSetIncrement, message, flags).DoubleResult;
        }

        public long SortedSetLength(string key, double min = -1.0 / 0.0, double max = 1.0 / 0.0, StackExchange.Redis.Exclude exclude = Exclude.None, StackExchange.Redis.CommandFlags flags = CommandFlags.None)
        {
            var message = new SortedSetLengthMessage(key, min, max, exclude);
            return Execute(RedisCommand.SortedSetLength, message, flags).LongResult;
        }

        public string[] SortedSetRangeByRank(string key, long start = 0, long stop = -1, StackExchange.Redis.Order order = Order.Ascending, StackExchange.Redis.CommandFlags flags = CommandFlags.None)
        {
            var message = new SortedSetRangeByRankMessage(key, start, stop, order);
            var result = Execute(RedisCommand.SortedSetRangeByRank, message, flags).RedisValueArrayResult;
            return RedisValueConverter.Convert(result);
        }

        public string[] SortedSetRangeByScore(string key, double start = -1.0 / 0.0, double stop = 1.0 / 0.0, Exclude exclude = Exclude.None, Order order = Order.Ascending, long skip = 0, long take = -1, CommandFlags flags = CommandFlags.None)
        {
            var message = new SortedSetRangeByScoreMessage(key, start, stop, exclude, order, skip, take);
            var result = Execute(RedisCommand.SortedSetRangeByScore, message, flags).RedisValueArrayResult;
            return RedisValueConverter.Convert(result);
        }

        public bool SortedSetRemove(string key, string member, StackExchange.Redis.CommandFlags flags = CommandFlags.None)
        {
            var message = new SortedSetRemoveMessage(key, member);
            return Execute(RedisCommand.SortedSetRemove, message, flags).BoolResult;
        }

        #region Async

        public async Task<bool> SortedSetAddAsync(string key, string member, double score, When when = When.Always, CommandFlags flags = CommandFlags.None)
        {
            var message = new SortedSetAddMessage(key, member, score, when);
            return await ExecuteAsync(RedisCommand.SortedSetAdd, message, flags).ContinueWith(t =>
            {
                return t.Result.BoolResult;
            }).ConfigureAwait(false);
        }

        public async Task<double> SortedSetDecrementAsync(string key, string member, double value, CommandFlags flags = CommandFlags.None)
        {
            var message = new SortedSetDecrementMessage(key, member, value);
            return await ExecuteAsync(RedisCommand.SortedSetDecrement, message, flags).ContinueWith(t =>
            {
                return t.Result.DoubleResult;
            }).ConfigureAwait(false);
        }

        public async Task<double> SortedSetIncrementAsync(string key, string member, double value, CommandFlags flags = CommandFlags.None)
        {
            var message = new SortedSetIncrementMessage(key, member, value);
            return await ExecuteAsync(RedisCommand.SortedSetIncrement, message, flags).ContinueWith(t =>
            {
                return t.Result.DoubleResult;
            }).ConfigureAwait(false);
        }

        public async Task<long> SortedSetLengthAsync(string key, double min = -1.0 / 0.0, double max = 1.0 / 0.0, Exclude exclude = Exclude.None, CommandFlags flags = CommandFlags.None)
        {
            var message = new SortedSetLengthMessage(key, min, max, exclude);
            return await ExecuteAsync(RedisCommand.SortedSetLength, message, flags).ContinueWith(t =>
            {
                return t.Result.LongResult;
            }).ConfigureAwait(false);
        }

        public async Task<string[]> SortedSetRangeByRankAsync(string key, long start = 0, long stop = -1, Order order = Order.Ascending, CommandFlags flags = CommandFlags.None)
        {
            var message = new SortedSetRangeByRankMessage(key, start, stop, order);
            return await ExecuteAsync(RedisCommand.SortedSetRangeByRank, message, flags).ContinueWith((task) =>
            {
                return RedisValueConverter.Convert(task.Result.RedisValueArrayResult);
            }).ConfigureAwait(false);
        }

        public async Task<string[]> SortedSetRangeByScoreAsync(string key, double start = -1.0 / 0.0, double stop = 1.0 / 0.0, Exclude exclude = Exclude.None, Order order = Order.Ascending, long skip = 0, long take = -1, CommandFlags flags = CommandFlags.None)
        {
            var message = new SortedSetRangeByScoreMessage(key, start, stop, exclude, order, skip, take);
            return await ExecuteAsync(RedisCommand.SortedSetRangeByScore, message, flags).ContinueWith((task) =>
            {
                return RedisValueConverter.Convert(task.Result.RedisValueArrayResult);
            }).ConfigureAwait(false);
        }

        public async Task<bool> SortedSetRemoveAsync(string key, string member, CommandFlags flags = CommandFlags.None)
        {
            var message = new SortedSetRemoveMessage(key, member);
            return await ExecuteAsync(RedisCommand.SortedSetRemove, message, flags).ContinueWith(t =>
            {
                return t.Result.BoolResult;
            }).ConfigureAwait(false);
        }

        #endregion
    }
}
